/**
 * @file 列表-操作插件
 * @author yangjiangming <449654337@qq.com>
 * @date 2018-12-10 20:13:16
 */
layui.define(['layer', 'zmnUtils', '$http', 'tooltipster'], function (exports) {

    var $ = layui.$;
    var zmnUtils = layui.zmnUtils;
    var $http = layui.$http;
    var tooltipster = layui.tooltipster;

    /**
     * 操作器插件
     * @param config
     * @constructor
     */
    function Modifier (config) {
        this.init(config);
    }

    /**
     * 默认配置
     * @type {{operateListURL: string, operateObjectURL: string}}
     */
    Modifier.prototype.config = {
        /**
         * 获取操作对象列表 URL
         */
        operateListURL: '',

        /**
         * 获取操作对象 URL
         */
        operateObjectURL: '',

        /**
         * UI 控制
         */
        ui: {
            header: true, // 头部栏
            preAndNext: true // 上下按钮
        },
        // 弹窗关闭回调
        end: function (data) {
        },
        // 特殊处理函数
        specialHandler: function () {
        },
        // 参数转换
        paramsParser: function (rowData) {
            var params = {};

            Object.assign(this.config.fields).forEach(function (key) {
                params[key] = rowData[key];
            });

            return params;
        }
    };

    Modifier.prototype.getConfig = function () {
        return this.config;
    };

    Modifier.prototype.getHomeOp = function () {
        return this.getOpConfigById(this.config.operateIdEnum.home);
    };

    /**
     * 数据缓存
     * @type {{current: {}, data: Array}}
     */
    Modifier.prototype.cache = {
        /**
         * 列表数据
         */
        dataList: [],
        /**
         * 当前数据
         */
        current: {},
        index: 0,
        operateId: null
    };

    Modifier.prototype.initCache = function (cacheObj) {
        if (cacheObj) {
            this.cache = cacheObj;
            return;
        }

        this.setDataList(window.dataList);

        var queryParams = zmnUtils.getQueryParams();
        var index = this.findIndex(queryParams);
        var rowData = this.getRowData(index);

        this.setOperateId(queryParams['operateId']);
        this.setCurrentData(rowData);
        this.setIndex(index);
    };

    Modifier.prototype.getDataList = function (data) {
        return this.cache.dataList;
    };

    Modifier.prototype.setDataList = function (data) {
        if (!zmnUtils.isArray(data)) {
            data = [];
        }
        this.cache.dataList = data;
    };

    Modifier.prototype.getRowDataByParams = function (params) {
        var key = this.config.primaryKey;
        var value = params[key];

        return this.getDataList().find((item) => {
            return item[key] === value;
        });
    };

    Modifier.prototype.getRowData = function (index) {
        return this.getDataList()[index];
    };

    Modifier.prototype.getLength = function (data) {
        return this.getDataList().length;
    };

    Modifier.prototype.setCurrentData = function (curr) {
        this.cache.current = curr;
    };

    Modifier.prototype.setCurrentDataByParams = function (params) {
        var rowData =  this.getRowDataByParams(params);

        this.setCurrentData(rowData);
    };

    Modifier.prototype.getCurrentData = function () {
        return this.cache.current;
    };

    Modifier.prototype.getParams = function () {
        var current = this.getCurrentData();


        var params = this.config.paramsParser(current);

        if (this.config.moduleId) {
            params['moduleId'] = this.config.moduleId;
        }

        return params;
    };

    Modifier.prototype.findIndex = function (rowData) {
        var key = this.config.primaryKey;
        var value = rowData[key];

        return this.getDataList().findIndex((item) => {
            return item[key] === value;
        });
    };

    Modifier.prototype.getIndex = function () {
        return this.cache.index;
    };

    Modifier.prototype.setIndex = function (index) {
        this.cache.index  = index;
    };

    Modifier.prototype.setOperateId = function (id) {
        this.cache.operateId  = id;
    };

    Modifier.prototype.getNext = function () {
        var length = this.getLength();
        var index = this.getIndex();
        var rowData = null;

        if (length && index < length - 1 ) {
            ++index;

            rowData = this.getRowData(index);

            this.setIndex(index);
            this.setCurrentData(rowData);
        }

        return rowData;
    };

    Modifier.prototype.getPrev = function (index) {
        var length = this.getLength();
        var index = this.getIndex();
        var rowData = null;

        if (length && index > 0 ) {
            --index;

            rowData = this.getRowData(index);

            this.setIndex(index);
            this.setCurrentData(rowData);
        }

        return rowData;
    };

    /**
     * 初始化插件
     * @param config
     */
    Modifier.prototype.init = function (config) {
        Object.assign(this.config, config);
    };

    /**
     * 获取操作列表
     * @param params
     * @returns {*}
     */
    Modifier.prototype.fetchOperationList = function (params) {
        return $http.$get(this.config.operateListURL, params);
    };

    /**
     * 检查操作权限
     * @param params
     * @returns {*}
     */
    Modifier.prototype.fetchOperationObj = function (params) {
        return $http.$get(this.config.operateObjectURL, params);
    };

    /**
     * 打开对话框
     * @param {Object} config 配置
     */
    Modifier.prototype.openDialog = function (config) {
        var that = this;
        var defaultConfig = {
            type: 2,
            content: '/',
            title: '',
            shade: [0.8, '#393D49'],
            area: ['98%', '96vh'],
            minWidth: '960px',
            zIndex: layer.zIndex, // 重点1
            success: function (layero) {
                parent.layer.setTop(layero); // 重点2
                var iframeWindow = layero.find('iframe')[0].contentWindow;
                iframeWindow.dataList = that.getDataList();
            }
        };

        var normalizedConfig = Object.assign({}, defaultConfig, config);
        parent.layer.open(normalizedConfig);
    };

    /**
     * 根据操作 id 获取配置中的操作对象
     * @param id
     * @returns {*|{}}
     */
    Modifier.prototype.getOpConfigById = function (id) {
        let operationList = this.config.operationList;
        return operationList.find((op) => op.id === +id) || {};
    };

    Modifier.prototype.createURL = function (url) {
         return (this.config.sysBaseURL || '') + url;
    };

    /**
     * 操作按钮点击事件
     * @param title
     * @param operateId
     * @param params
     * @param isPage
     */
    Modifier.prototype.operateHandler  = function ({ title, operateId, params }, isPage) {
        var that = this;

        that.setOperateId(operateId);

        var opConfigObj = that.getOpConfigById(operateId);
        var config = $.extend({}, params, { type: operateId });

        that.fetchOperationObj(config).done(function (operate) {
            if (operate && operate.canOperate) {
                var url = opConfigObj ? opConfigObj.url : '';
                params['operateId'] = operateId;

                // 特殊处理
                if (opConfigObj && opConfigObj.special) {
                    if (zmnUtils.isFunction(that.config.specialHandler)) {
                        that.config.specialHandler(params, opConfigObj);
                    }
                    return;
                }

                if (!url) {
                    layer.msg('操作暂不可用');
                    return;
                } else if (!params) {
                    layer.msg('参数不全');
                    return;
                }

                /**
                 * 1. 操作页在本页打开
                 * 2. 列表页打开弹窗
                 */
                if (isPage) {
                    // 更新弹窗 title
                    that.updateTitile(title);

                    // 跳转
                    window.location.href = zmnUtils.serializeURL(url, params);
                } else {
                    layer.closeAll();
                    url = that.createURL(url);

                    that.setCurrentDataByParams(params);

                    that.openDialog({
                        title: title,
                        content: zmnUtils.serializeURL(url, params),
                        end: function () {
                            if (zmnUtils.isFunction(that.config.end)) {
                                that.config.end();
                            }
                        }
                    });
                }
            } else {
                layer.msg(operate.msg)
            }
        });
    };

    /**
     * 绑定操作面板按钮事件
     * @param htmlStr
     * @param params
     * @returns {jQuery}
     */
    Modifier.prototype.bindEventForOperateButton = function (htmlStr, params) {
        let that = this;

        return $(htmlStr).on('click', 'button', function () {
            var $button = $(this);

            that.operateHandler({
                title: $button.text(),
                operateId: $button.data('id'),
                params: params
            });
        });
    };

    /**
     * 渲染操作面板
     * @param params
     * @param instance
     */
    Modifier.prototype.renderOperationPanel = function (params, instance) {
        this.fetchOperationList(params).done((data) => {
            var htmlStr = _createOperationPanelHtml(data);
            var $htmlStr = this.bindEventForOperateButton(htmlStr, params);

            instance.content($htmlStr);
        });
    };

    /**
     * 回到操作主页
     */
    Modifier.prototype.goOperateHome = function (params) {
        params = params || this.getParams();

        var homeOp = this.getHomeOp();
        params.operateId = homeOp.id;

        this.setOperateId(homeOp.id);

        window.location.href = zmnUtils.serializeURL(homeOp.url, params);
    };

    /**
     * 打开主页
     */
    Modifier.prototype.openHomeDialog = function (cb) {
        var homeOp = this.getHomeOp();
        var url = this.createURL(homeOp.url);

        this.setOperateId(homeOp.id);

        var params = this.getParams();

        this.openDialog({
            title: homeOp.title,
            content: zmnUtils.serializeURL(url, params),
            end: function () {
                if (zmnUtils.isFunction(cb)) {
                    cb();
                }
            }
        });
    };

    /**
     * 更新弹框标题
     * @param {string} title 标题
     */
    Modifier.prototype.updateTitile = function (title) {
        var index = zmnUtils.layui.getLayerIndex();
        parent.layui.$('#layui-layer' + index).find('.layui-layer-title').text(title);
    };

    /**
     * 初始化操作面板
     * @param {object} externalOptions 外部选项
     * @param {function} getParamFunc 获取操作按钮上绑定的参数
     */
    Modifier.prototype.initOperatePanel = function (externalOptions) {
        var defaultOption = {
            content: 'Loading...',
            side: 'left',
            theme: 'tooltipster-layui',
            interactive: true,
            contentAsHTML: true,
            animationDuration: '11111111111111',
            maxWidth: 430,
            updateAnimation: 'null',
            functionBefore: (instance, helper) => {
                var $origin = $(helper.origin);
                var index = $origin.closest('tr').data('index');
                var rowData = this.getRowData(index);

                this.setCurrentData(rowData);
                this.setIndex(index);

                var params = this.getParams();

                this.renderOperationPanel(params, instance);
            },
            functionPosition: function (instance, helper, pos) {
                // pos.size =  {
                //     height: 'auto',
                //     width: 430
                // };

                return pos;
            },
        };

        var options = Object.assign({}, defaultOption, externalOptions);

        $('.btn-operate').tooltipster(options);
    };

    /**
     * 初始化操作页面事件
     */
    Modifier.prototype.initOperatePageEvent = function () {
        let that = this;

        // 监听操作面板的点击事件
        $('.operator-panel').on('click', 'button', function (e) {
            var $button = $(this);
            var params = zmnUtils.getQueryParams();

            that.operateHandler({
                title: $button.text(),
                operateId: $button.data('id'),
                params: params
            }, true);
        });

        _getPrevNextButtonWrapper().on('click', 'button', function (e) {
            var $this = $(this);
            var action = $(this).data('action');
            var text = {
                prev: '到顶啦',
                next: '没有更多啦'
            };

            var rowData;

            if (action === 'prev') {
                rowData = that.getPrev();
            } else if (action === 'next') {
                rowData = that.getNext();
            }

            if (rowData === null) {
                layer.msg(text[action]);
                return;
            }
            that.setCurrentDataByParams(rowData);
            that.goOperateHome();
        });
    };

    /**
     * 初始化操作页面
     */
    Modifier.prototype.initOperatePage = function () {
        this.initCache();

        this.initOperatePageEvent();

        _initOperationListStatus();

        // 是否需要头部
        if (!this.config.ui.header) {
            $('#operate-header').hide();
        }

        // 是否需要上下按钮
        if (this.config.ui.preAndNext) {
            _getPrevNextButtonWrapper().show();
        }

        Pace.once('done', () => {
            _initPrevNextButtonStatus(this.getDataList(), this.getIndex());
        });
    };

    /**
     * 生成工单操作下拉列表
     * @param {array} data 数据
     * @returns {string} html 字符串
     */
    function _createOperationPanelHtml (data) {
        var htmlStr = '<div class="operator-panel">';

        $.each(data, function (index, item) {
            var classArr = ['layui-btn', 'layui-btn-primary', 'layui-btn-sm'];
            if (!item.canOperate) {
                classArr.push('layui-btn-disabled');
            }

            htmlStr += '<button class="' + classArr.join(' ') +
                '" data-url="' + item.url + '" data-id="' + item.id + '">' + item.name +'</button>'

        });

        htmlStr += '</div>';

        return htmlStr;
    }

    /**
     * 初始化操作列表按钮状态
     */
    function _initPrevNextButtonStatus (dataList, index) {
        function _enabledBtn ($btn) {
            $btn.removeClass('layui-disabled');
        }

        if (index === -1 || dataList.length === 1) {
            return;
        }

        var $buttons = _getPrevNextButtonWrapper().find('button');
        var $prev = $buttons.filter('[data-action="prev"]');
        var $next = $buttons.filter('[data-action="next"]');

        if (index === 0) {
            _enabledBtn($next);
        } else if (index >= dataList.length -1) {
            _enabledBtn($prev);
        } else {
            _enabledBtn($buttons);
        }
    }

    /**
     * 初始化操作列表按钮状态
     */
    function _initOperationListStatus () {
        var operateId = zmnUtils.getQueryString('operateId');
        $('#operator-panel .layui-btn[data-id="' +operateId + '"]').addClass('active');
    }

    /**
     * 获取上一页下一页按钮的包裹层
     * @returns {pe.fn.init|jQuery|HTMLElement}
     * @private
     */
    function _getPrevNextButtonWrapper () {
        return $('#operation-header .header-left');
    }

    /**
     * 程序入口
     */
    function _init (config) {
        var modifier = new Modifier(config);

        return modifier;
    }

    exports('listModifier', {
        init: _init
    });
});
